package com.weifly.weistock.module.stockmonitor.impl;

import com.weifly.weistock.bo.DiffRateBO;
import com.weifly.weistock.core.constant.StockCatalogEnum;
import com.weifly.weistock.core.market.StockMarketService;
import com.weifly.weistock.core.market.StockPriceDto;
import com.weifly.weistock.core.market.bo.StockDayBO;
import com.weifly.weistock.core.market.bo.StockKLineBO;
import com.weifly.weistock.core.monitor.MonitorConstants;
import com.weifly.weistock.core.task.AbstractUpdateService;
import com.weifly.weistock.core.task.UpdateStatus;
import com.weifly.weistock.core.util.CalculateUtils;
import com.weifly.weistock.module.stockbill.StockBillHoldService;
import com.weifly.weistock.module.stockbill.bo.StockRecordBO;
import com.weifly.weistock.module.stockbill.bo.StockSummaryBO;
import com.weifly.weistock.module.stockdata.StockDataHoldService;
import com.weifly.weistock.module.stockmonitor.StockMonitorHoldService;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorConfigBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorDayBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorHoldBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorStatusBO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 逻辑处理
 *
 * @author weifly
 * @since 2020/12/02
 */
public class StockMonitorCheckAction {

    public static final int CHECK_ALL = 1; // 检查所有
    public static final int CHECK_HF = 2; // 检查大宗

    private Logger log = LoggerFactory.getLogger(StockMonitorCheckAction.class);

    private StockMarketService stockMarketService;

    private StockDataHoldService stockDataHoldService;

    private StockMonitorHoldService stockMonitorHoldService;

    private StockBillHoldService stockBillHoldService;

    public void setStockMarketService(StockMarketService stockMarketService) {
        this.stockMarketService = stockMarketService;
    }

    public void setStockDataHoldService(StockDataHoldService stockDataHoldService) {
        this.stockDataHoldService = stockDataHoldService;
    }

    public void setStockMonitorHoldService(StockMonitorHoldService stockMonitorHoldService) {
        this.stockMonitorHoldService = stockMonitorHoldService;
    }

    public void setStockBillHoldService(StockBillHoldService stockBillHoldService) {
        this.stockBillHoldService = stockBillHoldService;
    }

    public void checkIfNeed(UpdateStatus updateStatus) {
        // 更新状态
        this.stockMonitorHoldService.updateStatus(updateStatus);
        int dayOfWeek = updateStatus.getCheckDayOfWeek();
        boolean workDay = (dayOfWeek == Calendar.MONDAY || dayOfWeek == Calendar.TUESDAY || dayOfWeek == Calendar.WEDNESDAY || dayOfWeek == Calendar.THURSDAY || dayOfWeek == Calendar.FRIDAY);

        // 更新实时数据
        if (updateStatus.getPreStatus() == AbstractUpdateService.STATUS_INIT) {
            this.check(CHECK_ALL);
        } else if (updateStatus.getStatus() == AbstractUpdateService.STATUS_RUN) {
            updateStatus.setSleepTime(10000); // 10秒执行一次
            int todayTime = updateStatus.getCheckHour() * 3600000 + updateStatus.getCheckMinute() * 60000 + updateStatus.getCheckSecond() * 1000;
            if (MonitorConstants.TIME_9HOUR_15MINUTE <= todayTime && todayTime <= MonitorConstants.TIME_15HOUR_3MINUTE) {
                this.check(CHECK_ALL); // 监控所有
            } else {
                this.check(CHECK_HF); // 仅监控大宗
            }
        } else if (workDay) {
            this.check(CHECK_HF); // 工作日，仅监控大宗
        }

        // 更新天数据
        // 在考虑
    }

    public void check(int checkRange) {
        for (StockMonitorHoldBO stockHoldBO : this.stockMonitorHoldService.getStockList()) {
            if (checkRange == CHECK_ALL) {
                this.checkOneStock(stockHoldBO);
            } else if (checkRange == CHECK_HF) {
                StockCatalogEnum stockCatalog = stockHoldBO.getStockMonitorConfig().getStockCatalog();
                if (StockCatalogEnum.HF_STOCK.equals(stockCatalog)) {
                    this.checkOneStock(stockHoldBO);
                }
            }
        }
    }

    private void checkOneStock(StockMonitorHoldBO stockHoldBO) {
        String stockCode = stockHoldBO.getStockMonitorConfig().getStockCode();
        StockKLineBO stockKLineBO = this.stockDataHoldService.getStockData(stockCode);
        if (stockKLineBO == null || stockKLineBO.getDayList() == null || stockKLineBO.getDayList().isEmpty()) {
            log.info("无股票历史数据, stockCode=" + stockCode);
            return;
        }
        StockPriceDto stockPriceDto = this.stockMarketService.getStockPriceByFullCode(stockCode);
        if (stockPriceDto == null || stockPriceDto.getNowPrice() == null || stockPriceDto.getNowPrice() <= 0) {
            log.info("无股票价格数据, stockCode=" + stockCode);
            return;
        }

        StockMonitorStatusBO statusBO = new StockMonitorStatusBO();
        // 计算状态信息
        this.calcStatusInfo(statusBO, stockKLineBO, stockPriceDto);
        // 计算交易信息
        this.calcTradeInfo(statusBO, stockHoldBO.getStockMonitorConfig());
        // 更新status
        stockHoldBO.setStockMonitorStatus(statusBO);
    }

    private void calcStatusInfo(StockMonitorStatusBO statusBO, StockKLineBO stockKLineBO, StockPriceDto stockPriceDto) {
        String priceDate = stockPriceDto.getPriceDate().replaceAll("-", ""); // 2021-07-13 -> 20210713
        statusBO.setPriceDate(priceDate);
        statusBO.setPriceTime(stockPriceDto.getPriceTime());
        statusBO.setNowPrice(stockPriceDto.getNowPrice());
        // 涨跌幅
        DiffRateBO diffRateBO = CalculateUtils.calcDiffAndRate(stockPriceDto.getYesterdayClosePrice(), stockPriceDto.getNowPrice());
        statusBO.setNowRate(diffRateBO.getRate());
        // 上涨百分比、下跌百分比
        Map<String, StockMonitorDayBO> dayMap = new StockMonitorConfigCalculator(this.mergeDayList(stockKLineBO, stockPriceDto, priceDate)).calc();
        StockMonitorDayBO monitorDayBO = dayMap.get(priceDate);
        statusBO.setUp_rate(monitorDayBO.getUp_rate());
        statusBO.setUp_rate_all_percent(monitorDayBO.getUp_rate_all_percent());
        statusBO.setDown_rate(monitorDayBO.getDown_rate());
        statusBO.setDown_rate_all_percent(monitorDayBO.getDown_rate_all_percent());
        statusBO.setDiff_rate_percent(monitorDayBO.getDiff_rate_percent());
    }

    private List<StockDayBO> mergeDayList(StockKLineBO stockKLineBO, StockPriceDto stockPriceDto, String priceDate) {
        List<StockDayBO> dayList = new ArrayList<>();
        StockDayBO lastDay = stockKLineBO.getDayList().get(stockKLineBO.getDayList().size() - 1);
        if (lastDay.getDay().equals(priceDate)) {
            // 同一天
            dayList.addAll(stockKLineBO.getDayList().subList(0, stockKLineBO.getDayList().size() - 2));
        } else {
            // 不同天
            dayList.addAll(stockKLineBO.getDayList());
        }
        StockDayBO todayBO = new StockDayBO();
        todayBO.setDay(priceDate);
        todayBO.setOpen(stockPriceDto.getNowPrice());
        todayBO.setHigh(stockPriceDto.getHighPrice());
        todayBO.setLow(stockPriceDto.getLowPrice());
        todayBO.setClose(stockPriceDto.getNowPrice());
        dayList.add(todayBO);
        return dayList;
    }

    private void calcTradeInfo(StockMonitorStatusBO statusBO, StockMonitorConfigBO configBO) {
        String tradeStockCode = configBO.getTradeStockCode();
        if (StringUtils.isEmpty(tradeStockCode)) {
            return; // 无交易标的
        }
        StockPriceDto tradeStockPriceDto = this.stockMarketService.getStockPriceByFullCode(tradeStockCode);
        if (tradeStockPriceDto == null || tradeStockPriceDto.getNowPrice() == null || tradeStockPriceDto.getNowPrice() <= 0) {
            log.info("无股票价格数据, stockCode=" + tradeStockCode);
            return;
        }

        statusBO.setTradeStockCode(tradeStockPriceDto.getCode());
        statusBO.setTradeStockName(tradeStockPriceDto.getName());
        // 涨跌幅
        DiffRateBO diffRateBO = CalculateUtils.calcDiffAndRate(tradeStockPriceDto.getYesterdayClosePrice(), tradeStockPriceDto.getNowPrice());
        statusBO.setTradeNowPrice(tradeStockPriceDto.getNowPrice());
        statusBO.setTradeNowRate(diffRateBO.getRate());

        // 最后成交信息
        String shortStockCode = tradeStockCode.substring(tradeStockPriceDto.getStockCatalog().getExchangePrefix().length());
        StockSummaryBO stockSummaryBO = this.stockBillHoldService.getStockSummary(shortStockCode);
        if (stockSummaryBO != null && stockSummaryBO.getRecordList().size() > 0) {
            StockRecordBO lastRecord = stockSummaryBO.getRecordList().get(stockSummaryBO.getRecordList().size() - 1);
            if (lastRecord.getTradePrice() != null && lastRecord.getTradePrice() > 0) {
                statusBO.setTradeLastPrice(lastRecord.getTradePrice());
                DiffRateBO lastDiffRateBO = CalculateUtils.calcDiffAndRate(lastRecord.getTradePrice(), tradeStockPriceDto.getNowPrice());
                statusBO.setTradeLastRate(lastDiffRateBO.getRate());
            }
        }
    }
}
